Skip to content

feat(libc): implement sceLibcBacktraceSelf on Windows - #2

Closed
ycbuzi wants to merge 45 commits into
mainfrom
agent/windows-backtrace
Closed

ycbuzi wants to merge 45 commits into
mainfrom
agent/windows-backtrace

Conversation

@ycbuzi

@ycbuzi ycbuzi commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

What

sceLibcBacktraceGetBufferSize and sceLibcBacktraceSelf threw NotImplemented on Windows. This implements them there with the record layout and frame order the Linux implementation already uses.

On Windows, guest modules are unwound from their DWARF tables (.ehfram), which the Windows stack walkers do not read. So the frames come from this libc's own _Unwind_Backtrace, and each return address is mapped to its module with GetModuleHandleExW. boykopovar#7083 takes its frames from the same source, but it writes a different record layout from the one merged upstream.

GuestBacktrace now also runs on Windows, using GetModuleHandleExW and RtlLookupFunctionEntry in place of dladdr.

This branch is based on upstream 252cbc29b, which is newer than this fork's main. The diff below therefore includes upstream commits; the change itself is commit ec5c0c398. It is staged here before going upstream.

Tested

Linux (cloud container, GCC): I temporarily built the Windows capture path on Linux, replacing backtrace(), with the _Unwind_Backtrace frame source, two skipped frames and module offsets. It passed the portable guest_backtrace test. The Linux code on this branch is unchanged from upstream.

Windows: not built or run yet. Both sources pass a MinGW-w64 GCC 13 syntax check, but upstream requires GCC 15.2. tools/check_conventions.py --base upstream/main passes.

Checklist

  • Based on current main; no other open PR implements the same functions (based on upstream 252cbc29b; git commit -m "feat(libc): implement guest backtrace capture" boykopovar/AnyPS5#7083 implements the same functions with another record layout)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

🤖 Generated with Claude Code

https://claude.ai/code/session_011krDVCnnMQPaEFEqCDnKmA

ErenYeager1836 and others added 30 commits October 18, 2026 10:15
Transition dialog status to finished in sceG2PDialogClose, matching the behavior in libSceSigninDialog, and add unit test coverage in GuestG2PDialog.
The expected count in the failure message of the staged clear sampled
read test is Threads * 4u + SampleTexelBytes, a std::size_t, but was
formatted with %u. On LP64 hosts that is the only -Wformat warning in
the tree, and the message would print the wrong value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…loop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
reachingWriter followed only fall-through and direct branches, so a V#
load on a path that reaches the loop through an s_setpc_b64 jump the
control flow analysis resolves was not seen, and another load could be
taken as the only writer. The walk now follows those jumps. It also
fails at s_call_b64 targets, whose callers it does not follow, instead
of walking from a function entry into the code above it.

Co-Authored-By: Claude <noreply@anthropic.com>
The PS5 module checks max_image_width - 1 > 999999 in
scePngDecQueryMemorySize and scePngDecCreate and returns
0x80690003 (INVALID_PARAM). This returned 0x80690002 (INVALID_SIZE)
and accepted a width of 1000001.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceUserServiceInitialize reads the thread priority from the first int
of its parameters, and sceUserServiceInitialize2 takes it as its
argument. A PS5 returns 0x80960005 for a priority outside 0x100 to
0x2FF, and 0x80960003 when Initialize2 is called on an initialized
service, where this returned success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A draw whose vertex shader exports the render target array index into a
color view of several slices of a 2D array target was refused. The view
now renders layers lastSlice - slice + 1 through a 2D array attachment
view of the array's resident image starting at its first slice, and the
draw marks every rendered slice dirty. A view of several slices of a
surface that is not a 2D array is still refused, as is a layered draw
without the array's resident image.

AI-assisted: yes
…of its view's slices

A layered draw into a color view of slices 0 to 5 of a 2D surface whose
CB_COLOR_ATTRIB3 declares one slice was refused. The CB clamps the
render target array index to the view's SLICE_MAX, not to the surface's
slice count, so each layer is written one slice pitch further on.
PPSA01317 renders a 512x512 cube map this way. Such a view now renders as
a 2D array of the view's last slice + 1 slices.

AI-assisted: yes
…the volume layer guard

The resident image of a 2D array color view only compared the view's own
slice offset with the image's layer pitch, which is trivially equal for
slice 0. Every slice of the array image is now checked against the slice
size DecodeColorBuffer offsets the view by. AttachmentView again requires
layer 0 for a 3D target, as it did before layered 2D array views.

AI-assisted: yes
A vertex shader exporting the render target index draws one value per
layer into a CB_COLOR_VIEW of slices 1 to 3 of a four-slice 2D array and
into slices 0 to 2 of a surface of one slice. After the write-back every
slice of guest memory must hold its layer's value, and the slices
outside the view (slice 0, and slice 3 of the one-slice surface) their
initial bytes.

AI-assisted: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g close

Transition dialog status to finished in sceNpAuthAuthorizedAppDialogClose, matching the behavior in libSceSigninDialog, and add unit test coverage in GuestNpAuthAuthorizedAppDialog.
Transition dialog status to finished in sceLoginDialogClose, matching the behavior in libSceSigninDialog, and add unit test coverage in GuestLoginDialog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…inished

fix(libSceVrSetupDialog): finish dialog on close
…horized-app-dialog-close-status

fix(libSceNpAuthAuthorizedAppDialog): transition to finished on dialog close
adriadam10 and others added 15 commits October 19, 2026 21:36
…lose-status

fix(libSceCdlgG2P): transition to finished on dialog close
…ample

fix(shader): sample a 3D T# through DIM 2D_ARRAY as a volume
…og-close-status

fix(libSceLoginDialog): transition to finished on dialog close
…sted-descriptor

fix(shader): link a table call whose descriptor load sits before its loop
…r-format

test(agc): print the staged clear's expected byte count as a size_t
…-initialize-priority

fix(libSceUserService): check the thread priority on initialization
…py-export-aliases

fix(relinker): allow Windows export aliases when probing backup copies
…-callback

fix(libSceNgs2): clear the voice callback on sampler and mixer setup
…te-max-width

fix(libScePngDec): reject a maximum image width above 1000000
…width-limit

fix(libScePngDec): enforce decode width limit
…alidation

fix(libScePngDec): validate custom decode pitch
…-waterfall-image-table

feat(recompiler): support waterfall select conditions and key bounds in pointer image tables
…ay-color-views

feat(agc): render layered draws into 2D array color views
…t-gate-20261018

feat: require matching recorded context in performance comparisons
sceLibcBacktraceGetBufferSize and sceLibcBacktraceSelf threw on Windows.
Guest modules there are unwound from their DWARF tables (.ehfram), which
the Windows stack walkers do not read, so the frames come from this
libc's own _Unwind_Backtrace, as boykopovar#7083 also does, and each return
address is mapped to its module with GetModuleHandleExW. The record
layout and the frame order are the Linux ones.

GuestBacktrace now runs on Windows too: the module and function of an
address come from GetModuleHandleExW and RtlLookupFunctionEntry there,
and from dladdr on Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011krDVCnnMQPaEFEqCDnKmA
@ycbuzi

ycbuzi commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

Closed: upstream boykopovar#8137 (open since 2026-10-19) implements the same two exports on Windows. Branch kept.

@ycbuzi ycbuzi closed this Oct 20, 2026
ycbuzi pushed a commit that referenced this pull request Oct 25, 2026
fix(agc): keep the host-pointer import's write window
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.